#include "forward_service.h"
#include "forward_util.h"
#include "raw_paraser.h"
#include "checksum_util.h"
#include "packet_handler_forward.h"
#include "pack_ip.h"
#include "pack_tcp.h"
#include "pack_udp.h"

#include <unistd.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/select.h>
#include <errno.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>

#define PRINT_RAW false

int get_packet(int fd, char* buff, size_t siz){
    bool ret = 0;

    fd_set fdsw, fdsr;
    FD_ZERO(&fdsw);
    FD_SET(fd, &fdsw);
    FD_ZERO(&fdsr);
    FD_SET(fd, &fdsr);
    struct timeval timeout={3, 0};

    int ret_sel = select(fd+1, &fdsr, &fdsw, NULL, &timeout);
    //LOGI("get_packet select=%d", ret_sel);
    if (ret_sel <= 0){
        ret = false;
    }else{

        if(FD_ISSET(fd, &fdsr)){
            //LOGI("can read");

            memset(buff, 0, siz);
            int bytes = read(fd, buff, siz);
            if (PRINT_RAW){
            	LOGI("========================= read=%d %d =========================", bytes, errno);
            }
            if (bytes <= 0 ){
            	if (PRINT_RAW){
            		LOGE("read failed!");
            	}
                ret = 0;
            }else if (bytes >= siz){
            	if (PRINT_RAW){
					LOGE("packet too long!");
				}
                ret = 0;
            }else{
                ret = bytes;
            }
        }

        if (FD_ISSET(fd, &fdsw)){
            // LOGI("can write");
        }

        if (!ret){
            memset(buff, 0, siz);
        }
    }
    //LOGI("get_packet ret=%d", ret);
    return ret;
}

void parase(int fd){

    char buf [4096] = {0};

    bool result = get_packet(fd, buf, 4096);
    if (result <= 0){
        return;
    }

    packet_handler_forward cb;
    int tot_len = paraseRaw(buf, &cb);

    // 直接写回给自己
    int ret = write(fd, buf, tot_len);
    if (PRINT_RAW){
    	LOGI("======================= write buffer %d =======================", ret);
    	paraseRaw(buf, NULL);
    }
}

int paraseRaw(char * buf, packet_handler* callback){

    pack_ip p_ip(buf);
    if (PRINT_RAW){
    	p_ip.print_buffer();
	}

    // 传输层起始位置
    char* ptr_transfer_layer = p_ip.get_transfer_layer();

    // 应用层起始位置
    char * ptr_app_layer = NULL;

    int protocol = p_ip.get_protocol();
    if (protocol == 6){
        // TCP头
        pack_tcp p_tcp(ptr_transfer_layer);
        if (PRINT_RAW){
        	p_tcp.print_buffer();
        }

        // 应用层起始位置
        ptr_app_layer = p_tcp.get_app_layer();

        if (callback != NULL){
        	callback->on_handle_tcp(p_ip.ptr, p_tcp.ptr);
            // 计算校验和
            calc_tcp_checksum(buf);
            check_tcp_checksum(buf);
        }else{
            check_tcp_checksum(buf);
        }
    }else if (protocol == 17){
        // UDP头
    	pack_udp p_udp(ptr_transfer_layer);
    	if (PRINT_RAW){
    		p_udp.print_buffer();
		}

        // 应用层起始位置
        ptr_app_layer = p_udp.get_app_layer();

        if (callback != NULL){
        	callback->on_handle_udp(p_ip.ptr, p_udp.ptr);
            // 计算校验和
            calc_udp_checksum(buf);
            check_udp_checksum(buf);
        }else{
            check_udp_checksum(buf);
        }
    }

    // 打印应用层数据
    if (ptr_app_layer != NULL){
        // 应用层长度
        int app_layer_len =  buf + p_ip.get_total_len() - ptr_app_layer;
        if (PRINT_RAW){
        	print_app_buffer(ptr_app_layer, app_layer_len);
		}
    }

    return p_ip.get_total_len();
}

void print_app_buffer(char* ptr, unsigned len){
	if (len > 0){
		LOGI("[APP] len=%d", len);
		forward_util::print_buff(ptr, len);
	}
}
